import logging
import shutil
from pathlib import Path

from fastapi import APIRouter

from app.models import ABRResponse, TQCDataRequest
from app.utils.buildAb import run_buildAb
from app.utils.common_utils import (
    ProcessingError,
    change_directory,
    determine_soc,
    setup_cache_directory,
    setup_tqc_data,
)
from app.utils.determine_type import determine_topology_type

router = APIRouter()
logger = logging.getLogger(__name__)


async def process_abr_decomp(cache_dir: Path):
    """处理ABR分解"""
    try:
        # 确定是否有SOC
        soc = determine_soc(cache_dir / "tqc.data")
        logger.info(f"确定SOC状态码: {soc}")

        # ABR分解不支持SOC
        if soc == 1:
            raise ProcessingError("ABR分解不支持自旋轨道耦合(SOC)")

        # 使用绝对路径定义所有文件
        atomwp_temp_path = cache_dir / "atomwp.in"
        source_file = cache_dir / "fort.603"
        result_file = cache_dir / "decompose_tqc.data"

        if not source_file.exists():
            raise ProcessingError(f"源文件 {source_file} 不存在，无法进行ABR分解，请先执行POS2ABR")
        if result_file.exists():
            result_file.unlink()

        # 复制文件
        shutil.copy(source_file, atomwp_temp_path)

        # 运行buildAb，需要在cache_dir中执行
        with change_directory(cache_dir):
            run_buildAb("tqc.data")

        # 读取结果文件
        posout_path = cache_dir / "posout"
        decompose_ebr_path = cache_dir / "decompose.601"
        decompose_abr_path = cache_dir / "decompose.603"

        # 读取posout
        posout_content = posout_path.read_text()

        # 读取eBR分解结果数量
        if not decompose_ebr_path.exists():
            raise ProcessingError("EBR分解未能生成 decompose.601 文件，请先执行EBR分解")

        decompose_ebr_content = decompose_ebr_path.read_text()
        lines = decompose_ebr_content.splitlines()

        try:
            num_ebr_solutions = int(lines[0].strip()) if lines else 0
        except (ValueError, IndexError):
            logger.warning(f"无法从 {decompose_ebr_path} 解析解的数量")
            num_ebr_solutions = -1

        # 读取aBR分解结果数量
        if not result_file.exists():
            raise ProcessingError("ABR分解未能生成 decompose_tqc.data 文件")
        shutil.copy(result_file, decompose_abr_path)
        logger.info(f"已生成ABR分解文件: {decompose_abr_path}")

        decompose_abr_content = decompose_abr_path.read_text()
        lines = decompose_abr_content.splitlines()

        try:
            num_abr_solutions = int(lines[0].strip()) if lines else 0
        except (ValueError, IndexError):
            logger.warning(f"无法从 {decompose_abr_path} 解析解的数量")
            num_abr_solutions = -1

        with change_directory(cache_dir):
            topology_type = determine_topology_type(num_ebr_solutions, num_abr_solutions)

        # 构建结果
        result = {
            "status": "success",
            "soc": soc,
            "abrs": posout_content,
            "num_ebr_solutions": num_ebr_solutions,
            "num_abr_solutions": num_abr_solutions,
            "decompose_abr_content": decompose_abr_content,
            **topology_type,
        }

        return ABRResponse.model_validate(result)
    except ProcessingError:
        raise
    except Exception as e:
        logger.exception(f"ABR分解处理错误: {str(e)}")
        raise ProcessingError(f"ABR分解处理错误: {str(e)}") from e


@router.post(
    "/abr_decomp",
    summary="原子带表示(aBR)分解",
    description="执行原子带表示分解，确定材料的拓扑类型(AI/OAI1/OAI2/TI)",
    response_description="返回aBR分解结果和材料类型分类",
    response_model=ABRResponse,
)
async def abr_decomposition(request: TQCDataRequest):
    """
    ## 原子带表示(aBR)分解分析

    执行原子带表示分解，基于原子轨道分析确定材料的精确拓扑类型。

    ### 功能说明：
    - 进行aBR分解计算
    - 确定材料的拓扑分类
    - 分析原子轨道贡献
    - 提供详细的分类依据

    ### 输入参数：
    - **poscar_content**: POSCAR文件的完整内容
    - **tqc_data**: TQC数据文件内容，包含占据带信息

    ### 返回结果：
    - **status**: 处理状态 ("success" 或 "error")
    - **soc**: 是否包含自旋轨道耦合效应
    - **abrs**: 原子带表示列表，包含原子轨道信息
    - **num_ebr_solutions**: eBR分解的解的数量
    - **num_abr_solutions**: aBR分解的解的数量
    - **decompose_abr_content**: 详细的aBR分解内容
    - **type**: 材料的拓扑类型分类
    - **conclusion**: 分析结论和分类依据
    - **additional_data**: 其他相关数据和信息

    ### 材料类型说明：
    - **AI**: 原子绝缘体 (Atomic Insulator) - 电子完全局域在原子上
    - **OAI1**: 阻塞原子绝缘体类型1 (Obstructed Atomic Insulator Type 1)
    - **OAI2**: 阻塞原子绝缘体类型2 (Obstructed Atomic Insulator Type 2)
    - **TI**: 拓扑绝缘体 (Topological Insulator) - 具有受保护的表面态
    """
    cache_dir = setup_cache_directory(request.poscar_content)
    setup_tqc_data(cache_dir, request.tqc_data)
    return await process_abr_decomp(cache_dir)
